/******************************************************************************

  File Name     : face_demo.cpp
  Version       : Initial Draft
  Author        : tongzhilin
  Created       : 2020/8/6
  Last Modified :
  Description   : face_demo
  Function List :
  History       :
  1.Date        : 2020/8/6
    Author      : tongzhilin
    Modification: Created file

******************************************************************************/
#include "image_container.h"
#include "mp_common.h"
#include "alg_struct.h"
#include "alg_api.h"

INT32 main()
{
    INT32 s32C = 0;
    INT32 s32H = 0;
    INT32 s32W = 0;
    ALG_INIT_PARAMS stInitParams;
    ALG_RECT_RESULT_S stFaceRectRst[64];
    ALG_FACELMK_RESULT_S stFaceLmkRst;
    ALG_FACEFEATURE_RESULT_S stFaceFeatureRst[2];

#ifdef ARCH_AARCH64
    //arm64 & arm
    system("echo 3 > /proc/sys/vm/drop_caches");
#endif

#ifdef INFERENCE_NNIE
    char cFaceDetModel[] = "../../models/nnie/facedetection_output_norm.wk";
    char cPfpldModel[] = "../../models/nnie/pfpld_merge_bn.wk";
    char cFaceFeatModel[] = "../../models/nnie/insightface_facefeature.wk";
#endif

#ifdef INFERENCE_MXNET
    char cFaceDetJson[] = "../../models/mxnet/facedetection_output_no_norm-symbol.json";
    char cFaceDetParams[] = "../../models/mxnet/facedetection_output_no_norm-0200.params";

    char cPfpldJson[] = "../../models/mxnet/pfpld-symbol.json";
    char cPfpldParams[] = "../../models/mxnet/pfpld-0200.params";

    char cFaceFeatJson[] = "../../models/mxnet/insightface_mobilefacenet_1-symbol.json";
    char cFaceFeatParams[] = "../../models/mxnet/insightface_mobilefacenet_1-0200.params";
#endif
    /*
    ** face detect
    */
    memset(&stInitParams, 0, sizeof(ALG_INIT_PARAMS));
#ifdef INFERENCE_NNIE
    stInitParams.m_eInferenceType = ALG_INFERENCE_NNIE;
    strcpy(stInitParams.unModel.stNnie.m_cWkFile, cFaceDetModel);
#endif
#ifdef INFERENCE_MXNET
    stInitParams.m_eInferenceType = ALG_INFERENCE_MXNET;
    strcpy(stInitParams.unModel.stMxnet.m_cJsonFile, cFaceDetJson);
    strcpy(stInitParams.unModel.stMxnet.m_cParamsFile, cFaceDetParams);
#endif
    ALG_HANDLE pstFaceDetV1 = Alg_Face_Detect_Init(&stInitParams);
    s32C = Alg_Face_Get_Input_C(pstFaceDetV1);
    s32H = Alg_Face_Get_Input_H(pstFaceDetV1);
    s32W = Alg_Face_Get_Input_W(pstFaceDetV1);
    MP_LOG_INFO("Face detect input image c : %d, h : %d, w : %d \n", s32C, s32H, s32W);
    std::string pathname = "../../images/test6.bmp";
    cv::Mat image = cv::imread(pathname, cv::IMREAD_COLOR);
    cv::Mat image_resize;
    cv::resize(image, image_resize, cv::Size(s32W, s32H));
    ALG_IMAGE_S stAlgImage = cv2alg(image_resize, 16);
    INT32 s32RecvNum = Alg_Face_Forward_Image(pstFaceDetV1, &stAlgImage, 64, stFaceRectRst);

    /*
    ** landmark 
    */
    memset(&stInitParams, 0, sizeof(ALG_INIT_PARAMS));
#ifdef INFERENCE_NNIE
    stInitParams.m_eInferenceType = ALG_INFERENCE_NNIE;
    strcpy(stInitParams.unModel.stNnie.m_cWkFile, cPfpldModel);
#endif
#ifdef INFERENCE_MXNET
    stInitParams.m_eInferenceType = ALG_INFERENCE_MXNET;
    strcpy(stInitParams.unModel.stMxnet.m_cJsonFile, cPfpldJson);
    strcpy(stInitParams.unModel.stMxnet.m_cParamsFile, cPfpldParams);
#endif
    ALG_HANDLE pstFaceLmkV1 = Alg_Face_LMK_Init(&stInitParams);
    s32C = Alg_Face_Get_Input_C(pstFaceLmkV1);
    s32H = Alg_Face_Get_Input_H(pstFaceLmkV1);
    s32W = Alg_Face_Get_Input_W(pstFaceLmkV1);
    MP_LOG_INFO("Face landmark input image c : %d, h : %d, w : %d \n", s32C, s32H, s32W);
#ifdef INFERENCE_NNIE
    std::string pathname1 = "/home/tzl/image_db/eval_face_feature/test3000/q/1865.bmp";
#else
    std::string pathname1 = "/mnt/image_db/eval_face_feature/test3000/q/1865.bmp";
#endif
    cv::Mat image1 = cv::imread(pathname1, cv::IMREAD_COLOR);
    cv::Mat image1_resize;
    cv::Mat image1_rgb;
    cv::resize(image1, image1_resize, cv::Size(s32W, s32H));
    cv::cvtColor(image1_resize, image1_rgb, CV_BGR2RGB);
    ALG_IMAGE_S stAlgImage1 = cv2alg(image1_rgb, 16);
    memset(&stFaceLmkRst, 0, sizeof(ALG_FACELMK_RESULT_S));
    Alg_Face_Forward_Image(pstFaceLmkV1, &stAlgImage1, 1, &stFaceLmkRst);

    /*
    ** face feature
    */
    memset(&stInitParams, 0, sizeof(ALG_INIT_PARAMS));
#ifdef INFERENCE_NNIE
    stInitParams.m_eInferenceType = ALG_INFERENCE_NNIE;
    strcpy(stInitParams.unModel.stNnie.m_cWkFile, cFaceFeatModel);
#endif
#ifdef INFERENCE_MXNET
    stInitParams.m_eInferenceType = ALG_INFERENCE_MXNET;
    strcpy(stInitParams.unModel.stMxnet.m_cJsonFile, cFaceFeatJson);
    strcpy(stInitParams.unModel.stMxnet.m_cParamsFile, cFaceFeatParams);
#endif
    ALG_HANDLE pstFaceFeatureV1 = Alg_Face_Feature_Init(&stInitParams);
    s32C = Alg_Face_Get_Input_C(pstFaceFeatureV1);
    s32H = Alg_Face_Get_Input_H(pstFaceFeatureV1);
    s32W = Alg_Face_Get_Input_W(pstFaceFeatureV1);
    MP_LOG_INFO("Face feature input image c : %d, h : %d, w : %d \n", s32C, s32H, s32W);
#ifdef INFERENCE_NNIE
    std::string pathname2 = "/home/tzl/image_db/eval_face_feature/test3000/q/1865.bmp";
#else
    std::string pathname2 = "/mnt/image_db/eval_face_feature/test3000/q/1865.bmp";
#endif
    cv::Mat image2 = cv::imread(pathname2, cv::IMREAD_COLOR);
    cv::Mat image2_resize;
    cv::Mat image2_rgb;
    cv::resize(image2, image2_resize, cv::Size(s32W, s32H));
    cv::cvtColor(image2_resize, image2_rgb, CV_BGR2RGB);
    ALG_IMAGE_S stAlgImage2 = cv2alg(image2_rgb, 16);
    memset(&stFaceFeatureRst[0], 0, sizeof(ALG_FACEFEATURE_RESULT_S));
    Alg_Face_Forward_Image(pstFaceFeatureV1, &stAlgImage2, 1, &stFaceFeatureRst[0]);

#ifdef INFERENCE_NNIE
    std::string pathname2_1 = "/home/tzl/image_db/eval_face_feature/test3000/g/1865.bmp";
#else
    std::string pathname2_1 = "/mnt/image_db/eval_face_feature/test3000/g/1865.bmp";
#endif
    cv::Mat image2_1 = cv::imread(pathname2_1, cv::IMREAD_COLOR);
    cv::Mat image2_1_resize;
    cv::Mat image2_1_rgb;
    cv::resize(image2_1, image2_1_resize, cv::Size(s32W, s32H));
    cv::cvtColor(image2_1_resize, image2_1_rgb, CV_BGR2RGB);
    ALG_IMAGE_S stAlgImage2_1 = cv2alg(image2_1_rgb, 16);
    memset(&stFaceFeatureRst[1], 0, sizeof(ALG_FACEFEATURE_RESULT_S));
    Alg_Face_Forward_Image(pstFaceFeatureV1, &stAlgImage2_1, 1, &stFaceFeatureRst[1]);

    Alg_Face_Feature_Cmp_Consin(&stFaceFeatureRst[0], &stFaceFeatureRst[1]);

    /*
    ** draw face result on image
    */
    for(INT32 i = 0; i < s32RecvNum; i++)
    {
        MP_LOG_INFO("Rect [%d], score:%.2f, x1 x2 y1 y2:[%.2f %.2f %.2f %.2f] \n", i, 
            stFaceRectRst[i].m_f32Score, stFaceRectRst[i].m_stRect.m_f32X1, stFaceRectRst[i].m_stRect.m_f32Y1, 
            stFaceRectRst[i].m_stRect.m_f32X2, stFaceRectRst[i].m_stRect.m_f32Y2);
        cv::rectangle(image_resize,
            cv::Point((INT32)stFaceRectRst[i].m_stRect.m_f32X1,
                    (INT32)stFaceRectRst[i].m_stRect.m_f32Y1),
            cv::Point((INT32)stFaceRectRst[i].m_stRect.m_f32X2,
                    (INT32)stFaceRectRst[i].m_stRect.m_f32Y2),
            cv::Scalar(0, 255, 0), 1);
        char buf[128] = {0};
        sprintf(buf, "score:%.2f", stFaceRectRst[i].m_f32Score);
        cv::putText(image_resize, std::string(buf),
            cv::Point((INT32)stFaceRectRst[i].m_stRect.m_f32X1 + 10,
                      (INT32)stFaceRectRst[i].m_stRect.m_f32Y1 + 10),
            cv::FONT_HERSHEY_SIMPLEX, 0.4, cv::Scalar(0, 255, 0));
    }
    std::string savepic = "../../images/_save_pic.jpg";
    cv::imwrite(savepic, image_resize);

    // signal lmk result
    for(INT32 i = 0; i < stFaceLmkRst.m_s32PointsNum; i++)
    {
        cv::circle(image1_resize,
            cv::Point{(int)stFaceLmkRst.m_stPoints[i].m_f32X, (int)stFaceLmkRst.m_stPoints[i].m_f32Y},
            1, cv::Scalar{255, 255, 0}, -1, 1);
    }
    std::string savepic1 = "../../images/_save_pic1.jpg";
    cv::imwrite(savepic1, image1_resize);

    return 0;
}
